Securing django with Let's Encrypt
You can also be interested in:
I just finished to setup ssl encryption for abidibo.net, using Let's Encrypt Certificate Authority. This post serves as a reminder for me, and maybe a sort of guide for you.
This post assumes the website runs with the following technologies:
- django >= 1.8
- nginx
- debian 8 (jessie) with ssh access
Why Let's Encrypt?
Let's Encrypt is a free, automated, and open certificate authority (CA), run for the public’s benefit. It is a service provided by the Internet Security Research Group (ISRG).
So, the interesting part is: it's free, and provides ssl certificates. That's it!
Some extracts from Let's Encrypt Getting Started guide:
In order to get a certificate for your website’s domain from Let’s Encrypt, you have to demonstrate control over the domain. With Let’s Encrypt, you do this using software that uses the ACME protocol, which typically runs on your web host.
I assume you have ssh access to your debian jessie powered machine, in that case:
We recommend that most people with shell access use the Certbot ACME client. It can automate certificate issuance and installation with no downtime. It also has expert modes for people who don’t want autoconfiguration. It’s easy to use, works on many operating systems, and has great documentation.
Let's go with Certbot...
Certbot, how to
Certbot is an easy-to-use automatic client that fetches and deploys SSL/TLS certificates for your webserver. Certbot was developed by EFF and others as a client for Let’s Encrypt and was previously known as “the official Let’s Encrypt client” or “the Let’s Encrypt Python client.”
In order to install Certbot you need to enable the Jessie backports repo, so edit your /etc/apt/sources.list
and add this line:
deb http://ftp.debian.org/debian jessie-backports main
Then perform an update:
$ sudo apt-get update
And you're ready to install Certbot:
$ sudo apt-get install certbot -t jessie-backports
Ok. In my case that wasn't enough, because I had an old pip version and an old request package version, so I received an error like this one:
AttributeError: 'module' object has no attribute 'PROTOCOL_SSLv3'
I solved it running:
$ sudo easy_install --upgrade pip $ pip install --upgrade requests
Now you should have Certbot properly installed in your system. Let's create the certificate!
The Certbot client supports a number of different “plugins” that can be used to obtain and/or install certificates, I'll use the webroot plugin, since it doesn't require to stop the web server.
To use the webroot plugin, your server must be configured to serve files from hidden directories. If /.well-known is treated specially by your webserver configuration, you might need to modify the configuration to ensure that files inside /.well-known/acme-challenge are served by the webserver.
What does it mean?
Before running the command which actually creates the certificate, you need to ensure that the web server can serve static files under the web root at the following path: /.well-know
. Since all paths intrcepted by the django application are served through wsgi, you need to write a nginx configuration role in order to serve statically such resources: add the following to your domain nginx configuration file:
location /.well-known { root /your/path; }
Where /your/path
is a directory which will be used when launching the Cerbot command. I decided to use the same directory which contains the folder static
, where the django static files are collected.
Reload nginx and you're ready to create the certificate:
$ certbot certonly --webroot -w /your/path -d example.com -d www.example.com
This command will obtain a single cert for example.com and www.example.com; it will place files below /your/path to prove control of the two domains.
You'll be asked to provide an e-mail address used for urgent notices and lost key recovery, and to accept the Let's Encrypt Subscribe Agreement. Easy!
You'll receive an output like this:
Output: IMPORTANT NOTES: - If you lose your account credentials, you can recover through e-mails sent to sammy@digitalocean.com - Congratulations! Your certificate and chain have been saved at /etc/letsencrypt/live/example.com/fullchain.pem. Your cert will expire on 2017-01-07. To obtain a new version of the certificate in the future, simply run Let's Encrypt again. - Your account credentials have been saved in your Let's Encrypt configuration directory at /etc/letsencrypt. You should make a secure backup of this folder now. This configuration directory will also contain certificates and private keys obtained by Let's Encrypt so making regular backups of this folder is ideal. - If like Let's Encrypt, please consider supporting our work by: Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate Donating to EFF: https://eff.org/donate-le
The certificate has been created and installed properly, now it's time to configure nginx and django to run over ssl, let's go!
Django
Here you can find the official documentation:
https://docs.djangoproject.com/en/1.10/topics/security/#ssl-https
In a nutshell, add these lines to your production configuration:
SESSION_COOKIE_SECURE=True SESSION_COOKIE_HTTPONLY=True SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTOCOL', 'https')
For applications running django<1.8 you should install and configure django-secure.
N.B. Make sure to load all external resources through https in your templates (js, fonts, css, images...), otherwise you'll get mixed content warnings.
Nginx
There's only one thing left: configure the nginx server block in order to serve the contents through HTTPS. I post my entire virtual host configuration and we'll discuss the ssl related lines.
server { listen 80; server_name abidibo.net www.abidibo.net; return 301 https://www.abidibo.net$request_uri; } server { listen 443 default ssl; ssl_certificate /etc/letsencrypt/live/abidibo.net/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/abidibo.net/privkey.pem; client_max_body_size 5M; server_name www.abidibo.net; access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; if (-f /home/abidibo/www/abidibo-net/releases/current/.maintenance) { return 503; } if (!-d /home/abidibo/www/abidibo-net/releases/current) { return 503; } error_page 503 @maintenance; location @maintenance { root /home/abidibo/www/abidibo-net/htdocs; rewrite ^(.*)$ /maintenance.html break; } location /.well-known { root /home/abidibo/www/abidibo-net; } location /static { root /home/abidibo/www/abidibo-net; } location /media { root /home/abidibo/www/abidibo-net; } location /robots.txt { root /home/abidibo/www/abidibo-net/htdocs/robots.txt; } location /sitemap.xml { root /home/abidibo/www/abidibo-net/htdocs/sitemap.xml.txt; } location / { uwsgi_pass unix:/tmp/uwsgi_abidibo-net.sock; include /etc/nginx/uwsgi_params; } }
Lines 1-5
all no-HTTP traffic is redirected to HTTPS
Line 8
listen on the 443 port
Lines 10-11
paths to the certicate and key (replace abidibo.net with your domain)
Lines 32-34
these ones where used during the creation of the certificate
#tadaaa it's done!
Reload nginx, deploy your django app and you should have your new, brilliant https site.
Your Smartwatch Loves Tasker!
Your Smartwatch Loves Tasker!
Featured
Archive
- 2021
- 2020
- 2019
- 2018
- 2017
- Nov
- Oct
- Aug
- Jun
- Mar
- Feb
- 2016
- Oct
- Jun
- May
- Apr
- Mar
- Feb
- Jan
- 2015
- Nov
- Oct
- Aug
- Apr
- Mar
- Feb
- Jan
- 2014
- Sep
- Jul
- May
- Apr
- Mar
- Feb
- Jan
- 2013
- Nov
- Oct
- Sep
- Aug
- Jul
- Jun
- May
- Apr
- Mar
- Feb
- Jan
- 2012
- Dec
- Nov
- Oct
- Aug
- Jul
- Jun
- May
- Apr
- Jan
- 2011
- Dec
- Nov
- Oct
- Sep
- Aug
- Jul
- Jun
- May